package com.request.proxy;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;

import java.util.Set;

/**
 * 扫描接口创建代理
 *
 * @author yuanqinglong
 * @since 2021/5/7 14:21
 */
public class ClassPathProxyScan extends ClassPathBeanDefinitionScanner {


    public ClassPathProxyScan(BeanDefinitionRegistry registry) {
        super(registry, false);
        addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
    }


    /**
     * 借助spring扫描器扫描配置包目录下的接口
     *
     * @param basePackages 扫描包路径
     * @return .
     */
    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        processBeanDefinitions(beanDefinitions);
        return beanDefinitions;
    }

    /**
     * 筛选出接口类型的对象
     *
     * @param beanDefinition bean描述
     * @return true or false
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    /**
     * 修改接口注册信息、
     *
     * @param beanDefinitions 。
     */
    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        for (BeanDefinitionHolder holder : beanDefinitions) {
            GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
            String beanClassName = definition.getBeanClassName();
            definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
            definition.setBeanClass(RequestProxyFactoryBean.class);
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        }
    }
}
